package com.semidata.trp.monitor.report;

import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.http.HttpResponse;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import com.semidata.rtd.core.http.client.HttpClient;
import com.semidata.rtd.core.http.client.HttpResponseHandler;
import com.semidata.rtd.core.log.Logger;
import com.semidata.rtd.core.service.Service;
import com.semidata.trp.message.business.Report;
import com.semidata.trp.message.business.Report.MonitorReport;
import com.semidata.trp.monitor.config.Config;

public class ReportService implements Service {

    private static final Config config = Config.getConfig();
    private ReportData data;
    private File dataFile;
    private long lastSendTime = 0;
    private static long SLEEP_TIME = 100;
    private static long SEND_TIME = 1000;
    private Thread thread;
    private boolean quit = false;
    private HttpClient client;

    @Override
    public void start() {
        File reportDataDir = new File(config.getReportDataDir());
        if (reportDataDir.exists()) {
            if (!reportDataDir.isDirectory() || !reportDataDir.canWrite() || !reportDataDir.canRead())
                throw new RuntimeException("report data dir is invalid: " + config.getReportDataDir());
        } else {
            if (!reportDataDir.mkdirs()) {
                throw new RuntimeException("can not create report data dir " + config.getReportDataDir());
            }
        }

        dataFile = new File(reportDataDir, "report.data");
        data = new ReportData();

        if (dataFile.exists()) {
            try {
				data.load(dataFile);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				data = new ReportData();
			}
        }
        
        client = new HttpClient();
        client.start();

        thread = new Thread(new Runnable() {

            @Override
            public void run() {

                while (!quit) {
                    Report.MonitorReport protoData = data.dump();
                    dump(protoData);

                    long currentTime = System.currentTimeMillis();
                    if (currentTime - lastSendTime > SEND_TIME) {
                        send(protoData);
                        //Logger.log("DEBUG", protoData.toString());
                        lastSendTime = currentTime;
                    }

                    try {
                        Thread.sleep(SLEEP_TIME);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }

            }

        });

        thread.start();

    }

    @Override
    public void stop() {
        quit = true;
        try {
        	if(thread != null){
        		thread.join();
        	}
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        Report.MonitorReport protoData = data.dump();
        dump(protoData);
        send(protoData);
        client.stop();
    }

    public ReportData getData() {
        return data;
    }

    public void dump(Report.MonitorReport protoData) {

        FileOutputStream out = null;
        try {
            out = new FileOutputStream(dataFile);
            out.write(protoData.toByteArray());
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            if (out != null)
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    private void send(MonitorReport protoData) {
        String url = config.getBusinessUrl();
        client.send(url, protoData.toByteArray(), new HttpResponseHandler() {

            @Override
            public void handle(HttpResponse response, ByteBuf buffer) {
                //Logger.log("DEBUG", response.getStatus().toString());
            }
            
        });
    }

}
